#ifndef ZAB_COMMUNICATION_H
#define ZAB_COMMUNICATION_H

#include "zab.h"
#include "misc_utils.h"
/*
 * To make things simpler, all packets have a similar structure:
 *
 * PACKET TYPE (2 bytes)
 * PACKET LENGTH (4 bytes) -- including the packet type and packet length
 * data
 *
 */
typedef struct ZAB_PACKET_T
{
    unsigned short type;
    unsigned int length;
    unsigned char data[1];

} ZAB_PACKET_T;

typedef enum PACKETIZE_STATE_T
{
    PACKETIZE_GETTING_TYPE,
    PACKETIZE_GETTING_LENGTH,
    PACKETIZE_GETTING_DATA
} PACKETIZE_STATE_T;

typedef void (*ZAB_PACKET_HANDLER_T)(ZAB_PACKET_T* packet, void* user_data);
typedef struct ZAB_PACKETIZER_T
{
    void* user_data;
    unsigned short packet_type;
    unsigned int packet_length;
    unsigned int index;
    PACKETIZE_STATE_T state;
    unsigned char buffer[4];    // buffer for an integer
    ZAB_PACKET_T* packet;
    ZAB_PACKET_HANDLER_T handler;
} ZAB_PACKETIZER_T;

void zab_packetizer_init(ZAB_PACKETIZER_T* packetizer, ZAB_PACKET_HANDLER_T handler, void* user_data);
void zab_packetizer_push(ZAB_PACKETIZER_T* packetizer, unsigned char* data, int length);
void zab_packetizer_push_byte(ZAB_PACKETIZER_T* packetizer, unsigned char byte);

///////////////////////////////////////////////////////////////////////////////
// packets
///////////////////////////////////////////////////////////////////////////////
typedef enum ZAB_PACKET_TYPE_T
{
    ZAB_PACKET_VOTE,
    ZAB_PACKET_NEW_EPOCH,
    ZAB_PACKET_NEW_EPOCH_ACK,
    ZAB_PACKET_NEW_LEADER,
    ZAB_PACKET_NEW_LEADER_ACK,
    ZAB_PACKET_PROPOSAL,
    ZAB_PACKET_ACK
} ZAB_PACKET_TYPE_T;


typedef struct ZXID_T
{
    unsigned int epoch;
    unsigned int count;
} ZXID_T;

// all the packets are just *parsed* payload
typedef struct ZAB_VOTE_MSG_T
{
    unsigned int node_id;
    unsigned int propsed_leader;
    ZXID_T proposed_zxid;
    unsigned int election_round;
    NODE_ROLE_T node_role;
    unsigned int node_epoch;
} ZAB_VOTE_MSG_T;

typedef struct ZAB_NEW_EPOCH_MSG_T
{
    unsigned int node_id;
    unsigned int epoch;
    ZXID_T zxid;
} ZAB_NEW_EPOCH_MSG_T;

typedef struct ZAB_NEW_EPOCH_ACK_MSG_T
{
    unsigned int node_id;
    unsigned int epoch;
    ZXID_T zxid;

} ZAB_NEW_EPOCH_ACK_MSG_T;

typedef struct ZAB_NEW_LEADER_MSG_T
{
    unsigned int leader_node;
    ZXID_T zxid;
} ZAB_NEW_LEADER_MSG_T;

typedef struct ZAB_NEW_LEADER_ACK_MSG_T
{
    unsigned int leader_node;
    ZXID_T zxid;
} ZAB_NEW_LEADER_ACK_MSG_T;

ZAB_PACKET_T* zab_vote_msg_encode(ZAB_VOTE_MSG_T* msg, PACKET_BUFFER_T* pb);
void zab_vote_msg_decode(ZAB_VOTE_MSG_T* msg, unsigned char* data, int length);

ZAB_PACKET_T* zab_new_epoch_msg_encode(ZAB_NEW_EPOCH_MSG_T* msg, PACKET_BUFFER_T* pb);
void zab_new_epoch_msg_decode(ZAB_NEW_EPOCH_MSG_T* msg, unsigned char* data, int length);

ZAB_PACKET_T* zab_new_epoch_ack_msg_encode(ZAB_NEW_EPOCH_ACK_MSG_T* msg, PACKET_BUFFER_T* pb);
void zab_new_epoch_ack_msg_decode(ZAB_NEW_EPOCH_ACK_MSG_T* msg, unsigned char* data, int length);

ZAB_PACKET_T* zab_new_leader_msg_encode(ZAB_NEW_LEADER_MSG_T* msg, PACKET_BUFFER_T* pb);
void zab_new_leader_msg_decode(ZAB_NEW_LEADER_MSG_T* msg, unsigned char* data, int length);

ZAB_PACKET_T* zab_new_leader_ack_msg_encode(ZAB_NEW_LEADER_ACK_MSG_T* msg, PACKET_BUFFER_T* pb);
void zab_new_leader_ack_msg_decode(ZAB_NEW_LEADER_ACK_MSG_T* msg, unsigned char* data, int length);

#endif // ZAB_COMMUNICATION_H
